/*
 * Copyright (c) 2015-2018 Sfkj Science And Technology Co.,Ltd.
 * All Rights Reserved.
 * This software is the confidential and proprietary information of
 * Sfkj Science And Technology Co.,Ltd.
 * ("Confidential Information").You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sfkj.
 */
package com.sfkj.walk.config;

import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.sfkj.walk.axon.interceptors.RequestHeaderInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.jackson.JacksonProperties;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.sfkj.walk.Contants.CACHE_CAPTCHA_EXPIRATION;
import static com.sfkj.walk.Contants.CACHE_CAPTCHA_NAME;

@Configuration
public class WebConfig {

    @Autowired
    private RedisTemplate redisTemplate;

    @Bean
    CacheManager cacheManager() {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        Map<String, Long> expires = new ConcurrentHashMap<>(1);
        expires.put(CACHE_CAPTCHA_NAME, CACHE_CAPTCHA_EXPIRATION);
        cacheManager.setExpires(expires);
        cacheManager.setCacheNames(Arrays.asList(CACHE_CAPTCHA_NAME));

        return cacheManager;
    }

    @Bean
    public RequestHeaderInterceptor requestHeaderInterceptor() {
        return new RequestHeaderInterceptor();
    }


    @Configuration
    @ConditionalOnClass({Jackson2ObjectMapperBuilder.class, LocalDateTimeSerializer.class})
    static class JodaDateTimeJacksonConfiguration {

        private static final Log logger = LogFactory.getLog(WebConfig.JodaDateTimeJacksonConfiguration.class);

        private final JacksonProperties jacksonProperties;

        JodaDateTimeJacksonConfiguration(JacksonProperties jacksonProperties) {
            this.jacksonProperties = jacksonProperties;
        }

        @Bean
        public SimpleModule localDateTimeSerializationModule() {
            SimpleModule module = new SimpleModule();
            DateTimeFormatter dateFormat = getDateFormat();
            if (dateFormat != null) {
                module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateFormat));
                module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateFormat));
            }
            return module;
        }

        private DateTimeFormatter getDateFormat() {
            if (this.jacksonProperties.getJodaDateTimeFormat() != null) {
                return DateTimeFormatter
                        .ofPattern(this.jacksonProperties.getJodaDateTimeFormat());
            }
            if (this.jacksonProperties.getDateFormat() != null) {
                try {
                    return DateTimeFormatter
                            .ofPattern(this.jacksonProperties.getDateFormat());
                } catch (IllegalArgumentException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("spring.jackson.date-format could not be used to "
                                + "configure formatting of Local DateTime. You may want "
                                + "to configure spring.jackson.time-format as "
                                + "well.");
                    }
                }
            }
            return null;
        }

    }

}